package contegor.scire.core.queries;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import contegor.scire.core.Concept;
import contegor.scire.core.Container;
import contegor.scire.core.Id;
import contegor.scire.core.IdFragment;
import contegor.scire.core.InfiniteSingletonList;
import contegor.scire.core.Link;
import contegor.scire.core.NeedsPrecedent;
import contegor.scire.core.ReturnPoint;
import contegor.scire.core.ScireException;

/**
 * Given a {@link Concept}s {@link Id}, returns the {@link Link}s who's source is that {@link Concept}.
 *
 * @version $Revision$
 * @author  Héctor Cirbián Pousa ($Author$)
 */
public class GetLinksFromSource extends QueryWithSubsequentsExtensible<Link, Link> {
  private static final long serialVersionUID = 5117096476150606707L;

  private IdFragment sourceId;
  private List<Link> results;

  public GetLinksFromSource(Id sourceId) {
    super(sourceId.getParentId());
    this.sourceId = sourceId.getLastIdFragment();
    this.subsequents = null;
    this.results = null;
  }

  @Override
  public void process(Container targetContainer) throws ScireException {
    Concept c = targetContainer.getConcept(sourceId);
    if ((c != null) && c.isVisibleTo(this.taskId.getTransactionId())) {
      this.returnPoint.manage(this.taskId, c.getLinks().values());
      if (this.results != null)
        this.results.addAll(c.getLinks().values());
      // FIXME: Container's Links are also Concept Links but this will produce inconsistencies.
      // Container's Links as Concept Links mechanism needs some more thinking.
    }
  }

  @Override
  public GetLinksFromSource withIt(NeedsPrecedent<? super Link, Link> subsequent) {
    if (this.results == null)
      this.results = new LinkedList<Link>(); 
    return (GetLinksFromSource)super.withIt(subsequent);
  }

  @Override
  public List<? extends Collection<Link>> getResultsForSubsequentTasks() {
    if ((this.subsequents == null) || (this.subsequents.size() == 0))
      return Collections.emptyList();
    if (this.results == null)
      this.results = Collections.emptyList();
    return new InfiniteSingletonList<List<Link>>(this.results, this.subsequents.size());
  }

  @Override
  public List<? extends ReturnPoint<? super Link>> getSubsequentTasksReturnPoints() {
    if ((this.subsequents == null) || (this.subsequents.size() == 0))
      return Collections.emptyList();
    return new InfiniteSingletonList<ReturnPoint<? super Link>>(this.returnPoint, this.subsequents.size());
  }
}